樣式設計其實是這個練習中最簡單的部分。
步驟在不同框架中通常是相同的。
tailwindcss 實用類別 (utility classes) 取代自訂 CSS 類別npm install tailwindcss@latest @tailwindcss/vite@latest daisyui@latest
在 Vite 中添加 Tailwind CSS
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
  plugins: [tailwindcss(), ...other plugins...],
});
在專案中先安裝 daisyUI 插件
@import "tailwindcss";
@plugin "daisyui";
npm install daisyui@latest tailwindcss@latest @tailwindcss/postcss@latest postcss@latest --force
配置檔案
// .postcssrc.json
{
  "plugins": {
    "@tailwindcss/postcss": {}
  }
}
在專案中先安裝 daisyUI 插件
// src/style.css
@import "tailwindcss";
@plugin "daisyui";
在 GithubProfileList 元件中,可以將 TailwindCSS 的類別 (class) 應用到標題(header)元素上,例如:
<div class="p-[0.75rem] col-span-full text-center">
    <h1 class="text-3xl">Github Profile List (Angular Ver.)</h1>
</div>
header 的 CSS 類別可以從樣式表 (style sheet) 中移除,改為使用 Tailwind CSS 的類別 (class) 來設定樣式 (style)。
另外,可以利用 TailwindCSS 的類別 (class) 來設計 CSS Grid 佈局,簡化自訂 CSS。
在 App 元件的模板中
<div class="grid grid-cols-2 pt-0 pb-0 pl-[2rem] pr-[2rem]">
    <GithubProfileList :usernames="usernames" />
</div>
// +layout.svelte
<div id="app" class="grid grid-cols-2 pt-0 pb-0 pl-[2rem] pr-[2rem]">
    {@render children()}
</div>
在 AppComponent 中使用 @Component 裝飾器時,可以修改 styles 屬性。
為了在 CSS 類別 (class) 使用 @apply,必須在配置中以 @reference 的方式包含 src/styles.css 檔案,確保不會重複包含該 CSS。
styles: `
    @reference "../../../styles.css";
    
    :host {
        @apply grid grid-cols-2 pt-0 pb-0 pl-[2rem] pr-[2rem]
    }
`,
Grid 佈局已成功應用於所有框架
CSS 樣式在範例中大致相同,但透過不同框架的控制流程語法 (control-flow syntax) 和資料插值語法 (interpolation),語法上會有所差異。
// GithubProfileCard.vue
<div class="card card-side bg-base-100 shadow-sm" v-if="profile">
    <figure class="basis-[30%] grow shrink">
      <img :src="profile.avatar_url" :alt="profile.name" />
    </figure>
    <div class="card-body basis-[70%] grow shrink">
      <h2 class="card-title">{{ profile.login }}</h2>
      <p>Name: {{ profile.name }}</p>
      <p>Bio: {{ profile.bio || 'N/A' }}</p>
      <p>Followers: {{ profile.followers }}</p>
      <p>Following: {{ profile.following }}</p>
      <p>Public Repos: {{ profile.public_repos }}</p>
      <div class="card-actions justify-end">
        <button class="btn btn-primary">
          <a :href="profile.html_url" target="_blank" rel="noopener noreferrer">
            <span class="text-white">View Profile</span>
          </a>
        </button>
      </div>
    </div>
  </div>
  <div v-else-if="error">Error: {{ error }}</div>
// github-profile-card.svelte
<div>
    {#if profile}
        <div class="card card-side bg-base-100 shadow-sm">
            <figure class="basis-[30%] grow shrink">
                <img src={profile.avatar_url} alt={profile.name} />
            </figure>
            <div class="card-body basis-[70%] grow shrink">
                <h2 class="card-title">{ profile.login }</h2>
                <p>Name: { profile.name }</p>
                <p>Bio: { profile.bio || 'N/A' }</p>
                <p>Followers: { profile.followers }</p>
                <p>Following: { profile.following }</p>
                <p>Public Repos: { profile.public_repos }</p>
                <div class="card-actions justify-end">
                    <button class="btn btn-primary">
                        <a href={profile.html_url} target="_blank" rel="noopener noreferrer">
                            <span class="text-white">View Profile</span>
                        </a>
                    </button>
                </div>
            </div>
        </div>
    {:else if error}
        <div>
            <p>Error: {error}</p>
        </div>
    {/if}
</div>
@let status = profileResource.status();
@if (status === 'loading') {
    <p>Loading profile...</p>
} @else if (status === 'error') {
    <p>Error loading profile: {{ error() }}</p>
} @else {
    @if (profile(); as profile) {
        <div class="card card-side bg-base-100 shadow-sm" v-if="profile">
            <figure class="basis-[30%] grow shrink">
              <img [src]="profile.avatar_url" [alt]="profile.name" />
            </figure>
            <div class="card-body basis-[70%] grow shrink">
              <h2 class="card-title">{{ profile.login }}</h2>
              <p>Name: {{ profile.name }}</p>
              <p>Bio: {{ profile.bio || 'N/A' }}</p>
              <p>Followers: {{ profile.followers }}</p>
              <p>Following: {{ profile.following }}</p>
              <p>Public Repos: {{ profile.public_repos }}</p>
              <div class="card-actions justify-end">
                <button class="btn btn-primary">
                  <a [href]="profile.html_url" target="_blank" rel="noopener noreferrer">
                    <span class="text-white">View Profile</span>
                  </a>
                </button>
              </div>
            </div>
          </div>
    } @else if (error()) { 
        @let message = error();
        <div>Error: {{ message }}</div>
    }
}